#include <fstream>
#include <boost/date_time/posix_time/posix_time.hpp>

#include <fastcgi++/request.hpp>
#include <fastcgi++/manager.hpp>

#include "ServerContext.h"
#include "Handler.h"
#include "DBPool.h"
#include "MemPool.h"

#define URI_PREFIX "/cgi-bin/"

void error_log(const char* msg)
{
	using namespace std;
	using namespace boost;
	static ofstream error;
	if(!error.is_open())
	{
		error.open("/tmp/errlog", ios_base::out | ios_base::app);
		error.imbue(locale(error.getloc(), new posix_time::time_facet()));
	}

	error << '[' << posix_time::second_clock::local_time() << "] " << msg << endl;
}

/*
	@brief 根据原始url获取相对url，比如原始uri为 /cgi-bin/test5/goods/getList?id=123 那么获取的相对uri为 /goods/getList，cgi文件名为test5
	@param origUri 原始uri，一般url格式为 /cgi-bin/cgi文件名/相对uri
	@return 获取成功返回相对uri,获取失败返回空
 */
std::string getReallUri(const std::string origUri){
	int start = origUri.find("/",1);
	if(start == std::string::npos){
		return "";
	}

	start = origUri.find("/",start + 1);
	if(start == std::string::npos){
		return "";
    }

	int end = origUri.find("?",start + 1);
	if(end == std::string::npos){
		end = origUri.length();
	}

	//去掉结尾的'/'
	if(origUri[end - 1] == '/'){
		end--;
	}

	return origUri.substr(start,end - start);
}

class Main : public Fastcgipp::Request<char> {

public:
    Main():
        Fastcgipp::Request<char>(5*1024){}
	
private:
	bool response(){

		std::string origUri = environment().requestUri;
		std::string uri = getReallUri(origUri);

		HandlerMapping* handlerMapping = HandlerMapping::getInstance();
		FastCgiHandler* handler = handlerMapping->getHandler(uri);

		if(handler){
//			handler->handle(*this);
            switch(environment().requestMethod) {
                case Fastcgipp::Http::RequestMethod::GET:
                        handler->doGet(this->environment(),this->out);
                        break;
                case Fastcgipp::Http::RequestMethod::POST:
                        handler->doPost(this->environment(),this->out);
                        break;
            }
		}else{
			//返回404错误信息
		}

		//out << "Content-Type: text/html; charset=utf-8\r\n\r\n";
		//out<< "1111111111111";

		return true;
	}

    bool inProcessor()
    {
        std::basic_string<char> data;

        data.assign(environment().postBuffer().cbegin(),environment().postBuffer().cend());

        std::multimap<std::basic_string<char>,
                std::basic_string<char>>* posts = const_cast<std::multimap<std::basic_string<char>,
                std::basic_string<char>>*>(&environment().posts);

        posts->insert(std::make_pair(std::move("data"),std::move(data)));

        return true;
    }
};

int main()
{

	///////////////////////////////////////////////////////////////////////////
	///环境上下文创建
	///////////////////////////////////////////////////////////////////////////
    Context* ctx = ServerContext::getInstance();

    if(ctx->initContext() != 0) {
        return 0;
    }

	///////////////////////////////////////////////////////////////////////////
	///此处添加逻辑handler
	///////////////////////////////////////////////////////////////////////////

    FastCgiHandler* adUrlHandler = new AdUrlHandler("/ad");
    FastCgiHandler* userRegHandler = new UserRegHandler("/user/register");
    FastCgiHandler* userLoginHandler = new UserLoginHandler("/user/login");

	///////////////////////////////////////////////////////////////////////////
    /// do not modify below !!!
    /////////////////////////////////////////////////////////////////////////// 

    Fastcgipp::Manager<Main> manager;
    manager.setupSignals();
    manager.listen();
    manager.start();
    manager.join();

    return 0;

//    try
//    {
//        // First we make a Fastcgipp::Manager object, with our request handling class
//        // as a template parameter.
//        Fastcgipp::Manager<Main> fcgi;
//        // Now just call the object handler function. It will sleep quietly when there
//        // are no requests and efficiently manage them when there are many.
//        fcgi.handler();
//    }
//    catch(std::exception& e)
//    {
//        error_log(e.what());
//    }
}
